home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Misc / DXInstall / dxinstall.cpp next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  16.5 KB  |  455 lines

  1. //-----------------------------------------------------------------------------
  2. // File: DxInstall.cpp
  3. //
  4. // Desc: Example code showing how to use DirectXSetup.
  5. //
  6. //       This file contains code that will handle all messages sent to the
  7. //       DirectXSetupCallbackFunction, with the filtering level set at what the
  8. //       user wants.  This way you can test to see which messages you want to
  9. //       handle automatically or pass on to the user.
  10. //
  11. //       Call Tree:
  12. //          DirectXInstallWndProc         See WINCODE.CPP
  13. //             DirectXInstall             Set up the callback and handle return codes
  14. //                 GetReply               See WINCODE.CPP
  15. //             DirectXGetVersion          Display the results of DirectXSetupGetVersion()
  16. //          DirectXSetupCallbackFunction  Called from DirectXSetup
  17. //             GetReply                   See WINCODE.CPP
  18. //             SetButtons                 See WINCODE.CPP
  19. //                ShowButton              See WINCODE.CPP
  20. //
  21. // Copyright (c) Microsoft Corporation. All rights reserved.
  22. //-----------------------------------------------------------------------------
  23. #include <windows.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <dsetup.h>
  27. #include "resource.h"
  28. #include "DXInstall.h"
  29.  
  30.  
  31.  
  32.  
  33. //-----------------------------------------------------------------------------
  34. // Externs for global variables
  35. //-----------------------------------------------------------------------------
  36. extern DWORD        g_dwStatus;         // Filter setting for messages from DirectXSetup
  37. extern HINSTANCE    g_hInstance;        // Global instance handle
  38. extern HWND         g_hDlg;             // Window handle to dialog proc
  39. extern CHAR         g_strAppTitle[256]; // Application title
  40. extern INT          g_iReply;           // Global value for dialog return
  41.  
  42.  
  43.  
  44. //--------------------------------------------------------------------------------------
  45. // DirectSetup dynamic linking support -- calls top-level dsetup.dll APIs with graceful
  46. // failure if APIs are not present.
  47. //--------------------------------------------------------------------------------------
  48. typedef INT (WINAPI * LPDIRECTXSETUPSETCALLBACK)( DSETUP_CALLBACK Callback );
  49. typedef INT (WINAPI * LPDIRECTXSETUPGETVERSION)(DWORD *lpdwVersion, DWORD *lpdwMinorVersion);
  50. #ifdef UNICODE
  51.     typedef INT (WINAPI * LPDIRECTXSETUP)( HWND hWnd, LPWSTR lpszRootPath, DWORD dwFlags );
  52. #else
  53.     typedef INT (WINAPI * LPDIRECTXSETUP)( HWND hWnd, LPSTR lpszRootPath, DWORD dwFlags );
  54. #endif 
  55.  
  56. // Module and function pointers
  57. static HMODULE                   s_hModDSetup = NULL;
  58. static LPDIRECTXSETUPSETCALLBACK s_DirectXSetupSetCallback = NULL;
  59. static LPDIRECTXSETUPGETVERSION  s_DirectXSetupGetVersion = NULL;
  60. static LPDIRECTXSETUP            s_DirectXSetup = NULL;
  61.  
  62.  
  63. //-----------------------------------------------------------------------------
  64. // Ensure function pointers are initialized
  65. //-----------------------------------------------------------------------------
  66. bool InitDirectSetupAPIs()
  67. {
  68.     // If module is non-NULL, this function has already been called.  Note
  69.     // that this doesn't guarantee that all D3D9 procaddresses were found.
  70.     if( s_hModDSetup != NULL )
  71.         return true;
  72.  
  73.     // This may fail if DirectX 9 isn't installed
  74.     s_hModDSetup = LoadLibrary( TEXT("dsetup.dll") );
  75.     if( s_hModDSetup == NULL ) 
  76.         return false;
  77.  
  78.     s_DirectXSetupSetCallback = (LPDIRECTXSETUPSETCALLBACK)GetProcAddress( s_hModDSetup, "DirectXSetupSetCallback" );
  79.     s_DirectXSetupGetVersion = (LPDIRECTXSETUPGETVERSION)GetProcAddress( s_hModDSetup, "DirectXSetupGetVersion" );
  80. #ifdef UNICODE
  81.     s_DirectXSetup = (LPDIRECTXSETUP)GetProcAddress( s_hModDSetup, "DirectXSetupW" );
  82. #else
  83.     s_DirectXSetup = (LPDIRECTXSETUP)GetProcAddress( s_hModDSetup, "DirectXSetupA" );
  84. #endif 
  85.  
  86.     return true;
  87. }
  88.  
  89.  
  90. //-----------------------------------------------------------------------------
  91. // Name: GetReply()
  92. // Desc: Waits for the user to click on a button on our simulated message box
  93. //       See DlgProc for the code that sets g_wReply
  94. //-----------------------------------------------------------------------------
  95. DWORD GetReply( DWORD dwMsgType )
  96. {
  97.     DWORD dwDefaultButton = 0;
  98.  
  99.     // Wait until DlgProc() lets us know that the user clicked on a button
  100.     while( g_iReply == -1 )
  101.     {
  102.         MSG msg;
  103.  
  104.         // Forward my messages...
  105.         while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
  106.         {
  107.             if( msg.message == WM_QUIT       ||
  108.                 msg.message == WM_CLOSE      ||
  109.                 msg.message == WM_SYSCOMMAND ||
  110.                 msg.message == WM_DESTROY )
  111.             {
  112.                 // Put the message back on the queue and get out of here.
  113.                 PostMessage( msg.hwnd, msg.message, msg.wParam, msg.lParam );
  114.                 break;
  115.             }
  116.             if( !IsDialogMessage( msg.hwnd, &msg ) )
  117.             {
  118.                 TranslateMessage( &msg );
  119.                 DispatchMessage( &msg );
  120.             }
  121.         }
  122.     }
  123.  
  124.     // Return the proper ID value for the button the user clicked on
  125.     // This code simulates what MessageBox() would return
  126.     switch( dwMsgType & 0x0000000F )
  127.     {
  128.         case MB_OKCANCEL:
  129.             dwDefaultButton = (g_iReply==IDBUT1) ? IDOK : IDCANCEL;
  130.             break;
  131.  
  132.         case MB_OK:
  133.             dwDefaultButton = IDOK;
  134.             break;
  135.  
  136.         case MB_RETRYCANCEL:
  137.             dwDefaultButton = (g_iReply==IDBUT1) ? IDRETRY : IDCANCEL;
  138.             break;
  139.  
  140.         case MB_ABORTRETRYIGNORE:
  141.             if( g_iReply == IDBUT1 )
  142.                 dwDefaultButton = IDABORT;
  143.             else if (g_iReply == IDBUT2)
  144.                 dwDefaultButton = IDRETRY;
  145.             else
  146.                 dwDefaultButton = IDIGNORE;
  147.             break;
  148.  
  149.         case MB_YESNOCANCEL:
  150.             if( g_iReply == IDBUT1 )
  151.                 dwDefaultButton = IDYES;
  152.             else if( g_iReply == IDBUT2 )
  153.                 dwDefaultButton = IDNO;
  154.             else
  155.                 dwDefaultButton = IDCANCEL;
  156.             break;
  157.  
  158.         case MB_YESNO:
  159.             dwDefaultButton = (g_iReply==IDBUT1) ? IDYES : IDNO;
  160.             break;
  161.  
  162.         default:
  163.             dwDefaultButton = IDOK;
  164.     }
  165.  
  166.     g_iReply = -1;
  167.  
  168.     return dwDefaultButton;
  169. }
  170.  
  171.  
  172.  
  173.  
  174. //-----------------------------------------------------------------------------
  175. // Name: DirectXSetupCallbackFunction()
  176. // Desc: Handle each reason for why the callback was called, filtering each
  177. //       message by what the current state of g_fStatus is.
  178. //-----------------------------------------------------------------------------
  179. DWORD WINAPI DirectXSetupCallbackFunction( DWORD dwReason, DWORD dwMsgType, 
  180.                                            LPSTR strMessage, LPSTR strName, 
  181.                                            VOID* pInfo )
  182. {
  183.     if( strMessage == NULL && strName == NULL )
  184.         return IDOK;
  185.  
  186.     if (dwReason == DSETUP_CB_MSG_PROGRESS) 
  187.     {
  188.         // Add code to update progress meter if there was one
  189.         return IDOK;
  190.     }    
  191.  
  192.     SetButtons( g_hDlg, 0xffffffff );
  193.     if( g_dwStatus == SHOW_ALL )
  194.     {
  195.         // Show all messages from DirectSetup
  196.         
  197.         SetWindowText( GetDlgItem( g_hDlg, ID_MYMESSAGE ), strMessage );
  198.  
  199.         // When dwMsgType is equal to zero we can display status information but
  200.         // should not wait for input from the user. 
  201.         if( dwMsgType == 0 )
  202.         {
  203.             Sleep(1000);
  204.             return IDOK;
  205.         }
  206.  
  207.         SetButtons( g_hDlg, dwMsgType );
  208.     }
  209.     else if( g_dwStatus == SHOW_UPGRADES )
  210.     {
  211.         // Show only upgrade messages
  212.  
  213.         switch( dwReason )
  214.         {
  215.             case DSETUP_CB_MSG_INTERNAL_ERROR:
  216.                 SetWindowText( GetDlgItem( g_hDlg, ID_MYMESSAGE ), strMessage );
  217.                 SetButtons( g_hDlg, dwMsgType );
  218.                 break;
  219.  
  220.             default:
  221.                 return IDOK;
  222.         }
  223.     }
  224.     else if( g_dwStatus == SHOW_PROBLEMS )
  225.     {
  226.         // Show only problem messages
  227.  
  228.         switch( dwReason )
  229.         {
  230.             case DSETUP_CB_MSG_INTERNAL_ERROR:
  231.                 SetWindowText( GetDlgItem( g_hDlg, ID_MYMESSAGE ), strMessage );
  232.                 SetButtons( g_hDlg, dwMsgType );
  233.                 break;
  234.  
  235.             default:
  236.                 return IDOK;
  237.         }
  238.     }
  239.     else if( g_dwStatus == SHOW_NONE )
  240.     {
  241.         // Don't show any messages
  242.         return IDOK;
  243.     }
  244.  
  245.     return GetReply( dwMsgType );
  246. }
  247.  
  248.  
  249.  
  250.  
  251. //-----------------------------------------------------------------------------
  252. // Name: DirectXGetVersion( HWND hWnd )
  253. // Desc: Shows the results of a call to DirectXSetupGetVersion()
  254. //-----------------------------------------------------------------------------
  255. VOID DirectXGetVersion( HWND hWnd )
  256. {
  257.     DWORD   dwVersion;
  258.     DWORD   dwRevision;
  259.  
  260.     if( InitDirectSetupAPIs() == false )
  261.     {
  262.         MessageBox( hWnd, TEXT("dsetup.dll could not be found.  In order to use the DirectSetup API, copy the entire contents of the Redist\\DirectX9 folder from the DirectX SDK into the same folder as this sample.  See the documenation and source for further details."), TEXT("Error"), MB_OK|MB_ICONINFORMATION );
  263.         return;
  264.     }
  265.  
  266.     s_DirectXSetupGetVersion( &dwVersion, &dwRevision );
  267.     // Use HIWORD(dwVersion); to get the DirectX major version
  268.     // Use LOWORD(dwVersion); to get the DirectX minor version
  269.     // For example: for DirectX 5 dwVersion == 0x00040005
  270.  
  271.     CHAR strBuf[128];
  272.     sprintf( strBuf, "Version 0x%08lX\nRevision %ld", dwVersion, dwRevision );
  273.     MessageBox( hWnd, strBuf, "Results:", MB_OK|MB_ICONINFORMATION );
  274. }
  275.  
  276.  
  277.  
  278.  
  279. //-----------------------------------------------------------------------------
  280. // Name: EnableReboot()
  281. // Desc: Enables reboot functionality on Win2k+
  282. //-----------------------------------------------------------------------------
  283. VOID EnableReboot(VOID)
  284. {
  285.     HANDLE hProcess = GetCurrentProcess();
  286.     HANDLE hToken;
  287.     if( OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken) )
  288.     {
  289.         LUID luidShutDown;
  290.         if( LookupPrivilegeValue( NULL, SE_SHUTDOWN_NAME, &luidShutDown ) )
  291.         {
  292.             TOKEN_PRIVILEGES Privilege;
  293.             Privilege.PrivilegeCount = 1;
  294.             Privilege.Privileges[0].Luid = luidShutDown;
  295.             Privilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  296.  
  297.             AdjustTokenPrivileges(hToken, FALSE, &Privilege, 0, NULL, NULL);
  298.         }
  299.     }
  300. }
  301.  
  302.  
  303.  
  304.  
  305. //-----------------------------------------------------------------------------
  306. // Name: DirectXInstall()
  307. // Desc: Set up the callback function for DirectXSetup and handle the return
  308. //       results.  This function starts a modeless version of MessageBox() so
  309. //       that the user can see the progress of the DirectX installation.
  310. //-----------------------------------------------------------------------------
  311. BOOL DirectXInstall( HWND hWnd )
  312. {
  313.     CHAR  strSource[_MAX_PATH];
  314.     CHAR  string[256];
  315.     INT   iRetCode;
  316.     DWORD dwFlags;
  317.  
  318.     if( InitDirectSetupAPIs() == false )
  319.     {
  320.         MessageBox( hWnd, TEXT("dsetup.dll could not be found.  In order to use the DirectSetup API, copy the entire contents of the Redist\\DirectX9 folder from the DirectX SDK into the same folder as this sample.  See the documenation and source for further details."), TEXT("Error"), MB_OK|MB_ICONINFORMATION );
  321.         return false;
  322.     }
  323.  
  324.     // The DSETUP DLLs should be at the current path, along with the DirectX
  325.     // redist directory so that it can be found and set up.  Otherwise, change
  326.     // the code below to reflect the real path.
  327.     GetCurrentDirectory( _MAX_PATH, strSource );
  328.  
  329.     // If the user wants any messages, bring up the simulated MessageBox
  330.     // dialog
  331.     if( g_dwStatus != SHOW_NONE )
  332.     {
  333.         // Create a modeless dialog box so we can show messages that don't
  334.         // need user input
  335.         g_hDlg = CreateDialog( g_hInstance, "INSTDX", hWnd, (DLGPROC)DlgProc );
  336.         if( g_hDlg == NULL )
  337.         {
  338.             CHAR buf[200];
  339.             LoadString( g_hInstance, STR_NODIALOG, buf, 200 );
  340.             MessageBox( hWnd, string, g_strAppTitle, MB_ICONSTOP|MB_OK );
  341.             return FALSE;
  342.         }
  343.  
  344.         ShowWindow( GetDlgItem( g_hDlg, IDBUT1 ), SW_HIDE );
  345.         ShowWindow( GetDlgItem( g_hDlg, IDBUT2 ), SW_HIDE );
  346.         ShowWindow( GetDlgItem( g_hDlg, IDBUT3 ), SW_HIDE );
  347.         ShowWindow( g_hDlg, SW_NORMAL );
  348.     }
  349.  
  350.     // Set the callback function up before calling DirectXSetup
  351.     s_DirectXSetupSetCallback( (DSETUP_CALLBACK)DirectXSetupCallbackFunction );
  352.     if( g_dwStatus != SHOW_NONE )
  353.     {
  354.         LoadString( g_hInstance, STR_STARTSETUP, string, 256 );
  355.         SetWindowText( GetDlgItem( g_hDlg, ID_MYMESSAGE ), string );
  356.         SetButtons( g_hDlg, 0xffffffff );
  357.         Sleep( 1000 );
  358.     }
  359.  
  360.     dwFlags = DSETUP_DIRECTX;
  361.     //-------------------------------------------------------------------------
  362.     // Notes: 
  363.     //
  364.     // 1) Test Install
  365.     //    If you just want to test the install process without
  366.     //    actually installing then add the DSETUP_TESTINSTALL flag like so:
  367.     //    dwFlags |= DSETUP_TESTINSTALL;
  368.     // 
  369.     //  2) Managed DirectX
  370.     //     To install Managed DirectX you must add the DSETUP_MANAGEDDX flag like so:
  371.     //     dwFlags |= DSETUP_MANAGEDDX
  372.     //
  373.     //     Managed DirectX requires the .NET Framework to be installed before 
  374.     //     installing DirectX.  DirectX does NOT install the .NET Framework.    
  375.     //-------------------------------------------------------------------------
  376.  
  377.     iRetCode = s_DirectXSetup( hWnd, strSource, dwFlags );
  378.  
  379.     // If the user didn't want any message, we now need to bring up the dialog
  380.     // to reflect the return message from DirectXSetup
  381.     if( g_dwStatus == SHOW_NONE )
  382.     {
  383.         g_hDlg = CreateDialog( g_hInstance, "INSTDX", hWnd, (DLGPROC)DlgProc );
  384.         if( g_hDlg == NULL )
  385.         {
  386.             CHAR buf[200];
  387.             LoadString( g_hInstance, STR_NODIALOG, buf, 200 );
  388.             MessageBox( hWnd, string, g_strAppTitle, MB_ICONSTOP|MB_OK );
  389.             return FALSE;
  390.         }
  391.  
  392.         ShowWindow( GetDlgItem( g_hDlg, IDBUT1 ), SW_HIDE );
  393.         ShowWindow( GetDlgItem( g_hDlg, IDBUT2 ), SW_HIDE );
  394.         ShowWindow( GetDlgItem( g_hDlg, IDBUT3 ), SW_HIDE );
  395.         ShowWindow( g_hDlg, SW_NORMAL );
  396.     }
  397.  
  398.     switch( iRetCode )
  399.     {
  400.         // Since our MessageBox dialog is still up, display the results in it
  401.         case DSETUPERR_NEWERVERSION:
  402.             MessageBox( hWnd, "Installation is newer than one being installed",
  403.                         "DirectX Setup", MB_OK );
  404.             break;
  405.  
  406.         case DSETUPERR_SUCCESS_RESTART:
  407.             LoadString( g_hInstance, STR_RESTART, string, 256 );
  408.             SetWindowText( GetDlgItem( g_hDlg, ID_MYMESSAGE ), string );
  409.             SetButtons( g_hDlg, 0xffffffff );
  410.             SetButtons( g_hDlg, MB_YESNO );
  411.             if( GetReply( MB_YESNO ) == IDYES )
  412.             {
  413.                 // Restart Windows
  414.                 EnableReboot();
  415.                 InitiateSystemShutdownEx( NULL,
  416.                                           NULL,
  417.                                           0,
  418.                                           FALSE,
  419.                                           TRUE,
  420.                                           SHTDN_REASON_MAJOR_OPERATINGSYSTEM |
  421.                                           SHTDN_REASON_MINOR_UPGRADE |
  422.                                           SHTDN_REASON_FLAG_PLANNED);
  423.             }
  424.             break;
  425.  
  426.         case DSETUPERR_SUCCESS:
  427.             LoadString( g_hInstance, STR_SUCCESS, string, 256 );
  428.             SetWindowText( GetDlgItem( g_hDlg, ID_MYMESSAGE ), string );
  429.             SetButtons( g_hDlg, 0xffffffff );
  430.             SetButtons( g_hDlg, MB_OK );
  431.             GetReply( MB_OK );
  432.             break;
  433.  
  434.         case DSETUPERR_BADWINDOWSVERSION:
  435.         case DSETUPERR_SOURCEFILENOTFOUND:
  436.         case DSETUPERR_NOCOPY:
  437.         case DSETUPERR_OUTOFDISKSPACE:
  438.         case DSETUPERR_CANTFINDINF:
  439.         case DSETUPERR_CANTFINDDIR:
  440.         case DSETUPERR_INTERNAL:
  441.         case DSETUPERR_UNKNOWNOS:
  442.             LoadString( g_hInstance, STR_ERRORRETURN + (iRetCode * -1) - 1, string, 256 );
  443.             SetWindowText( GetDlgItem( g_hDlg, ID_MYMESSAGE ), string );
  444.             SetButtons( g_hDlg, 0xffffffff );
  445.             SetButtons( g_hDlg, MB_OK );
  446.             GetReply( MB_OK );
  447.             break;
  448.     }
  449.  
  450.     DestroyWindow( g_hDlg );
  451.     g_hDlg = NULL;
  452.  
  453.     return TRUE;
  454. }
  455.